package simpledb.optimizer;

import simpledb.execution.OpIterator;
import simpledb.execution.Predicate;

/**
 * LogicalSubplanJoinNode 表示在逻辑查询计划（LogicalQueryPlan）中，
 * 一个表和子查询之间的连接操作所需的元数据。
 *
 * 它继承自 {@link LogicalJoinNode}，其中 t2 和 f2 始终为 null，
 * 因为子查询没有对应的第二个表和字段信息。
 */
public class LogicalSubplanJoinNode extends LogicalJoinNode {

    /**
     * 子查询的物理执行迭代器（OpIterator）
     * 在嵌套循环连接等算法中作为内表使用
     */
    final OpIterator subPlan;

    /**
     * 构造一个新的 LogicalSubplanJoinNode 实例
     *
     * @param table1 表1的别名（外表）
     * @param joinField1 外表用于连接的字段名称（可以是带表名前缀的格式）
     * @param sp 子查询的物理执行计划（OpIterator），作为连接的内表
     * @param pred 连接使用的谓词操作符（如 EQUALS、GREATER_THAN 等）
     */
    public LogicalSubplanJoinNode(String table1, String joinField1, OpIterator sp, Predicate.Op pred) {
        // 设置外表的别名
        t1Alias = table1;

        // 分割字段名，提取纯字段名（去除表名/别名前缀）
        String[] tmps = joinField1.split("[.]");
        if (tmps.length > 1)
            f1PureName = tmps[tmps.length - 1];
        else
            f1PureName = joinField1;

        // 构造限定字段名：tableAlias.fieldPureName
        f1QuantifiedName = t1Alias + "." + f1PureName;

        // 设置子查询计划
        subPlan = sp;

        // 设置连接操作符
        p = pred;
    }

    /**
     * 重写 hashCode 方法，用于唯一标识该 Join 节点
     */
    @Override
    public int hashCode() {
        return t1Alias.hashCode() + f1PureName.hashCode() + subPlan.hashCode();
    }

    /**
     * 重写 equals 方法，判断两个 LogicalSubplanJoinNode 是否相等
     */
    @Override
    public boolean equals(Object o) {
        // 必须是 LogicalJoinNode 的实例
        if (!(o instanceof LogicalSubplanJoinNode))
            return false;

        LogicalJoinNode j2 = (LogicalJoinNode) o;

        // 比较外表别名、字段名以及子查询计划是否一致
        return (j2.t1Alias.equals(t1Alias) && j2.f1PureName.equals(f1PureName) && ((LogicalSubplanJoinNode) o).subPlan
            .equals(subPlan));
    }

    /**
     * 交换内外表的方法（目前只是返回相同的结构）
     * 可用于优化连接顺序时尝试不同的组合
     *
     * @return 交换后的新的 LogicalSubplanJoinNode 对象
     */
    public LogicalSubplanJoinNode swapInnerOuter() {
        return new LogicalSubplanJoinNode(t1Alias, f1PureName, subPlan, p);
    }
}
